﻿@page "/timestampConversion";
@using System.Timers;
@using System.Globalization;
@using ClipLazor;
@using ClipLazor.Components;
@inject IClipLazor Clipboard;

<PageTitle>时间戳工具</PageTitle>

<div class="timestamp-container">
    <div class="current-time-section">
        <h1>时间戳转换工具</h1>
        <div class="current-time-display">
            <i class="fas fa-clock"></i>
            <span>当前时间: @currentTime</span>
        </div>
        <div class="current-timestamp-display">
            <div>
                <span>秒级时间戳:</span>
                <span class="timestamp-value">@currentTimestampSec</span>
            </div>
            <div>
                <span>毫秒级时间戳:</span>
                <span class="timestamp-value">@currentTimestampMs</span>
            </div>
            <div>
                <span>当前服务器时区:</span>
                <span class="timestamp-value">@serverTimeZone.Id</span>
            </div>
            <div>
                <span>当前UTC偏移量:</span>
                <span class="timestamp-value">@serverTimeZone.BaseUtcOffset</span>
            </div>
        </div>
    </div>

    <div class="conversion-section">
        <div class="conversion-card">
            <h2>时间戳转时间</h2>
            <div class="input-group">
                <input type="number" @bind="timestampInput" placeholder="输入时间戳..." />
                <div class="unit-selector">
                    <button class="btn @(isSeconds ? "btn-primary" : "btn-outline-primary")"
                            @onclick="() => { isSeconds = true; isMilliseconds = false; }">
                        秒级
                    </button>
                    <button class="btn @(isMilliseconds ? "btn-primary" : "btn-outline-primary")"
                            @onclick="() => { isMilliseconds = true; isSeconds = false; }">
                        毫秒级
                    </button>
                </div>
            </div>
            <button class="btn btn-success" @onclick="TimestampToDatetime">
                <i class="bi bi-arrow-left-right"></i> 转换
            </button>

            <div class="result-display">
                <label>转换结果:</label>
                <div class="result-box">
                    <span>@timestampResult</span>
                    <button class="btn btn-sm btn-outline-secondary" @onclick="@(e => CopyTxt(timestampResult))">
                        <i class="bi bi-clipboard-check-fill"></i> 复制
                    </button>
                </div>
            </div>

            <div class="action-buttons">
                <button class="btn btn-info" @onclick="UseCurrentTimestamp">
                    使用当前时间戳
                </button>
                <button class="btn btn-info" @onclick="UseRandomTimestamp">
                    使用随机时间戳
                </button>
            </div>
        </div>

        <div class="conversion-card">
            <h2>时间转时间戳</h2>
            <div class="datetime-input">
                               <div class="form-group">
                    <label>日期:</label>
                    <input type="date" value="@dateInput" />
                </div>
                <div class="form-group">
                    <label>时间:</label>
                    <input type="time" value="@timeInput" />
                </div>
            </div>
            <button class="btn btn-success" @onclick="DatetimeToTimeStamp">
                <i class="bi bi-arrow-left-right"></i> 转换
            </button>

            <div class="result-display">
                <label>秒级时间戳:</label>
                <div class="result-box">
                    <span>@secondsTimestampResult</span>
                    <button class="btn btn-sm btn-outline-secondary" @onclick="@(e => CopyTxt(secondsTimestampResult))">
                        <i class="bi bi-clipboard-check-fill"></i> 复制
                    </button>
                </div>
            </div>

            <div class="result-display">
                <label>毫秒级时间戳:</label>
                <div class="result-box">
                    <span>@millisTimestampResult</span>
                    <button class="btn btn-sm btn-outline-secondary" @onclick="@(e => CopyTxt(millisTimestampResult))">
                        <i class="bi bi-clipboard-check-fill"></i> 复制
                    </button>
                </div>
            </div>

            <div class="action-buttons">
                <button class="btn btn-info" @onclick="CurrentDateTimeToTimeStamp">
                    <i class="bi bi-clock"></i> 使用当前时间
                </button>
            </div>
        </div>
    </div>

    <div class="info-section">
        <h3><i class="bi bi-book-half"></i> 时间戳知识</h3>
        <p>
            <strong>Unix时间戳</strong>是从1970年1月1日（UTC/GMT的午夜）开始所经过的秒数，不考虑闰秒。
            时间戳在编程中被广泛使用，特别是在处理日期和时间相关的操作时。
        </p>
        <p>
            在C#中，可以使用 <code>DateTimeOffset.UtcNow.ToUnixTimeSeconds()</code> 获取秒级时间戳，
            <code>DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()</code> 获取毫秒级时间戳。
        </p>
    </div>
</div>
@code {
    private string currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    private Timer? secondsTimer;
    private long timestampInput = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    private string timestampResult = "";
    private string secondsTimestampResult = "";
    private string millisTimestampResult = "";
    private bool isSeconds = true;
    private bool isMilliseconds;
    private string dateInput = DateTime.Now.ToString("yyyy-MM-dd");
    private string timeInput = DateTime.Now.ToString("HH:mm");
    private long currentTimestampSec = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    private long currentTimestampMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
    private TimeZoneInfo serverTimeZone = TimeZoneInfo.Local;

    protected override void OnInitialized() {
        // 每秒更新一次当前时间
        secondsTimer = new Timer(1000);
        secondsTimer.Enabled = true;
        secondsTimer.AutoReset = true;
        secondsTimer.Elapsed += (sender, e) => UpdateTime();
    }

    private void UpdateTime() {
        currentTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        currentTimestampSec = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        currentTimestampMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
        InvokeAsync(StateHasChanged);
    }

    private void TimestampToDatetime() {
        try {
            long timestamp = timestampInput;

            // 如果是秒级时间戳，转换为毫秒
            if (isSeconds) {
                timestamp *= 1000;
            }

            DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(timestamp);
            DateTime dateTime = dateTimeOffset.ToLocalTime().DateTime;

            timestampResult = dateTime.ToString("yyyy-MM-dd HH:mm:ss");
        } catch (Exception ex) {
            timestampResult = $"转换错误: {ex.Message}";
        }
    }

    private void DatetimeToTimeStamp() {
        try {
            // 解析日期和时间
            DateTime dateTime = DateTime.Parse($"{dateInput} {timeInput}");

            DateTimeOffset dateTimeOffset = new DateTimeOffset(dateTime);

            // 计算时间戳
            long secondsTimestamp = dateTimeOffset.ToUnixTimeSeconds();
            long millisTimestamp = dateTimeOffset.ToUnixTimeMilliseconds();

            secondsTimestampResult = secondsTimestamp.ToString();
            millisTimestampResult = millisTimestamp.ToString();
        } catch (Exception ex) {
            secondsTimestampResult = $"转换错误: {ex.Message}";
            millisTimestampResult = $"转换错误: {ex.Message}";
        }
    }

    private void CurrentDateTimeToTimeStamp() {
        try {
            DateTime now = DateTime.Now;
            dateInput = now.ToString("yyyy-MM-dd");
            timeInput = now.ToString("HH:mm");

            // 触发转换
            DatetimeToTimeStamp();
        } catch (Exception ex) {
            secondsTimestampResult = $"转换错误: {ex.Message}";
            millisTimestampResult = $"转换错误: {ex.Message}";
        }
    }

    private void UseCurrentTimestamp() {
        timestampInput = currentTimestampSec;
        isSeconds = true;
        isMilliseconds = false;
    }

    private void UseRandomTimestamp() {
        // 生成2000到现在日期之间的随机时间戳
        DateTime start = new DateTime(2000, 1, 1);
        DateTime end = DateTime.Now;
        int range = (end - start).Days;
        DateTime randomDate = start.AddDays(new Random().Next(range));

        DateTimeOffset dateTimeOffset = new DateTimeOffset(randomDate);
        timestampInput = dateTimeOffset.ToUnixTimeSeconds();
        isSeconds = true;
        isMilliseconds = false;
    }
    string msg = string.Empty;
    string txt = string.Empty;
    string pastedTxt = string.Empty;

    private async void CopyTxt(string txt) {
        if (txt.Length > 0 && isSupported) {
            if (isWritePermitted) {
                var isCopied = await Clipboard.WriteTextAsync(txt.AsMemory());
                if (isCopied) {
                    msg = "Text Copied";
                } else {
                    msg = "Couldn't copy the text!.";
                }
            }
            StateHasChanged();
        }
    }
    async void PasteTxt() {
        if (isSupported && isWritePermitted) {
            var pastedText = await Clipboard.ReadTextAsync();
            if (pastedText is not null) {
                msg = "Text Pasted";
                pastedTxt = pastedText;
            } else {
                msg = "Couldn't paste the text!.";
            }
        }
        StateHasChanged();
    }
    bool isSupported = default;
    bool isWritePermitted = default;
    bool isReadPermitted = default;

    protected override async Task OnAfterRenderAsync(bool firstRender) {
        // 静态渲染期间无法进行js互操作，所以必须在这个周期点执行
        if (firstRender) {
            isSupported = await Clipboard.IsClipboardSupported();
            isWritePermitted = await Clipboard.IsPermitted(PermissionCommand.Write);
            isReadPermitted = await Clipboard.IsPermitted(PermissionCommand.Read);
        }
    }

    public void Dispose() {
        secondsTimer?.Dispose();
    }
}

<style>
    .timestamp-container {
        max-width: 1000px;
        margin: 0 auto;
        padding: 20px;
    }

    .current-time-section {
        background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
        color: white;
        padding: 20px;
        border-radius: 10px;
        margin-bottom: 30px;
        box-shadow: 0 5px 15px rgba(0,0,0,0.1);
    }

        .current-time-section h1 {
            margin-bottom: 20px;
            font-weight: 600;
        }

    .current-time-display {
        display: flex;
        align-items: center;
        gap: 10px;
        font-size: 1.5rem;
        margin-bottom: 15px;
    }

    .current-timestamp-display {
        display: flex;
        gap: 30px;
        font-size: 1.1rem;
    }

    .timestamp-value {
        font-family: 'Consolas', monospace;
        font-weight: bold;
        margin-left: 10px;
        background: rgba(255,255,255,0.2);
        padding: 5px 10px;
        border-radius: 5px;
    }

    .conversion-section {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 20px;
        margin-bottom: 30px;
    }

    .conversion-card {
        background: white;
        border-radius: 10px;
        padding: 20px;
        box-shadow: 0 5px 15px rgba(0,0,0,0.05);
    }

        .conversion-card h2 {
            color: #2c3e50;
            margin-bottom: 20px;
            display: flex;
            align-items: center;
            gap: 10px;
        }

    .input-group {
        display: flex;
        flex-direction: column;
        gap: 10px;
        margin-bottom: 15px;
    }

    input {
        padding: 12px;
        border: 1px solid #ddd;
        border-radius: 5px;
        font-size: 1rem;
    }

        input:focus {
            border-color: #2575fc;
            outline: none;
            box-shadow: 0 0 0 3px rgba(37, 117, 252, 0.2);
        }

    .unit-selector {
        display: flex;
        gap: 10px;
    }

    .datetime-input {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 15px;
        margin-bottom: 15px;
    }

    .form-group {
        display: flex;
        flex-direction: column;
    }

    label {
        margin-bottom: 5px;
        font-weight: 500;
    }

    select {
        padding: 10px;
        border: 1px solid #ddd;
        border-radius: 5px;
        font-size: 1rem;
    }

    .result-display {
        margin: 20px 0;
    }

    .result-box {
        display: flex;
        justify-content: space-between;
        align-items: center;
        background: #f8f9fa;
        padding: 10px 15px;
        border-radius: 5px;
        border-left: 3px solid #2575fc;
        margin-top: 5px;
    }

    .action-buttons {
        display: flex;
        gap: 10px;
        margin-top: 20px;
    }

    .btn {
        padding: 10px 15px;
        border-radius: 5px;
        cursor: pointer;
        transition: all 0.3s;
        display: flex;
        align-items: center;
        gap: 8px;
    }

    .btn-primary {
        background: #2575fc;
        color: white;
        border: none;
    }

    .btn-outline-primary {
        background: transparent;
        border: 1px solid #2575fc;
        color: #2575fc;
    }

    .btn-success {
        background: #28a745;
        color: white;
        border: none;
    }

    .btn-info {
        background: #17a2b8;
        color: white;
        border: none;
    }

    .btn-outline-secondary {
        background: transparent;
        border: 1px solid #6c757d;
        color: #6c757d;
    }

    .btn-sm {
        padding: 5px 10px;
        font-size: 0.9rem;
    }

    .info-section {
        background: white;
        border-radius: 10px;
        padding: 20px;
        box-shadow: 0 5px 15px rgba(0,0,0,0.05);
    }

        .info-section h3 {
            display: flex;
            align-items: center;
            gap: 10px;
            color: #2c3e50;
            margin-bottom: 15px;
        }

        .info-section p {
            margin-bottom: 10px;
            line-height: 1.6;
        }

    code {
        background: #f8f9fa;
        padding: 2px 6px;
        border-radius: 4px;
        font-family: 'Consolas', monospace;
    }
</style>